package base.thread_demo.demo17;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 使用jdk1.5 提供的线程并发库API提供了线程池功能
 * 线程池里的每一个线程代码结束后，并不会死亡，而是再次回到线程池中成为空闲状态，等待下一个对象来使用。
 *
 * 如何实现线程池的代码呢?
 * 		A:创建一个线程池对象，控制要创建几个线程对象。
 * 			public static ExecutorService newFixedThreadPool(int nThreads)
 * 		B:这种线程池的线程可以执行：
 * 			可以执行Runnable对象或者Callable对象代表的线程任务
 * 			做一个类实现Runnable接口。
 * 		C:调用如下方法即可
 * 			Future<?> submit(Runnable task)
 *			<T> Future<T> submit(Callable<T> task)
 *		D:我就要结束，可以吗?
 *			可以。
 *
 * Executors 负责创建线程池,可以创建多种类型线程池(单线程线程池,固定线程数据线程池,自动扩容线程数线程池).
 *
 * 线程池的好处就是:每个线程共享线程范围内的数据，从而保证每个任务只被一个线程处理。
 *
 * 本例演示: 10个任务添加到含有3个线程的线程池中待处理.
 *
 * 每次全部三个线程先把1-3号任务执行完毕，再次接着下一轮循环把4-6号任务完成，第三轮循环执行7-9号任务，
 * 最后只要一个线程把最后一号任务执行完毕，另外两个线程回到线程池中待命。
 *
 */
public class ThreadPool1 {
    private static final Logger log = LoggerFactory.getLogger(ThreadPool1.class);

    public static void main(String[] args) {
        // 创建由3个线程组成的线程池,该线程池重用这3个线程
        ExecutorService pool = Executors.newFixedThreadPool(3);
        //下面这是一种带缓冲线程池，当task服务不过来，会自动生成新线程来处理task,一般有多少任务就自动创建多少线程
        //ExecutorService pool2 = Executors.newCachedThreadPool();
        //下面是单线程线程池,始终保持池中只有一个线程在执行任务，假如一个线程死掉，立马新生成一线程继续执行任务
        //ExecutorService pool3 = Executors.newSingleThreadExecutor();


        /**
         * 往线程池扔10个任务(执行10次任务)，被3个线程处理，每个任务内部循环5次输出.
         *
         * 线程池的好处就是每个线程共享线程范围内的数据，从而保证每个任务只被一个线程处理。这就是说
         * 每个任务在5次循环过程中,始终由某一个线程去处理.
         *
         */
        for (int i = 0; i < 10; i++) {
            /**
             * 这个task纯粹是为了解决Runnable中打印输出要求是final变量而定义的，由此可见final的task指向i，
             * final修饰的task表示始终指向i，即使i是变动的，但指向是不变的。
             *
            final int task = i;
            pool.submit(new Runnable() {
                @Override
                public void run() {
                    for (int j = 0; j < 5; j++) {
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        log.info("{} is loop of {} for task {}", Thread.currentThread().getName(),j,task);
                    }
                }
            });
            */
            pool.submit(new MyRunnable(i));
        }

        log.info("all of 10 tasks have committed！ ");
        pool.shutdown();//等待任务被执行完，线程池就回收所有线程，程序结束
    }
}


class MyRunnable implements Runnable{
    private static final Logger log = LoggerFactory.getLogger(MyRunnable.class);
    int task;
    public MyRunnable(int task){
        this.task = task;
    }

    @Override
    public void run() {
        for(int j=1; j<=5; j++) {
            log.info("{} is loop of {} for task {}", Thread.currentThread().getName(),j,task);
        }
    }
}
